package com.guaniu.voip.ui.main;

import static com.guaniu.voip.sip.SipManager.CALL_CONNECTED;
import static com.guaniu.voip.sip.SipManager.CALL_DISCONNECTED;
import static net.gotev.sipservice.SipServiceConstants.BACK_CAMERA_CAPTURE_DEVICE;

import java.util.TimerTask;


import android.app.KeyguardManager;
import android.app.KeyguardManager.KeyguardLock;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo; 
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent; 
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.WindowManager;
import android.widget.Chronometer;
import android.widget.FrameLayout;
import android.widget.ImageButton; 
import android.widget.TextView;
import android.widget.Toast;

import com.guaniu.voip.BaseActivity;
import com.guaniu.voip.R;
import com.guaniu.voip.sip.Constant;
import com.guaniu.voip.sip.INetworkManager;
import com.guaniu.voip.sip.SipManager;
import com.guaniu.voip.ui.login.LoginActivity;

import net.gotev.sipservice.BroadcastEventReceiver;
import net.gotev.sipservice.Logger;
import net.gotev.sipservice.MediaState;
import net.gotev.sipservice.SipServiceCommand;
import net.gotev.sipservice.SipServiceConstants;

import org.pjsip.pjsua2.pjsip_inv_state;

public class VideoChatActivity extends BaseActivity implements OnClickListener , BroadcastEventReceiver.SipEventObserver{

	private static final String TAG = "VideoChatActivity";
  
	public static final String PREPARE_FOR_CALL_FLAG = "PREPARE_FOR_CALL_FLAG";
	
	private FrameLayout mViewRemoteVideoPreview;
	private FrameLayout mViewLocalVideoPreview;
	SurfaceView mSvLocal;
	SurfaceView mSvRemote;
	private FrameLayout mViewLocalVideoPreviewInCall;
	private ImageButton mSendVideo;
	private ImageButton mSwitchToAudio;
	private ImageButton mSwitchCamera;
	private ImageButton mSwitchMute;
	private ImageButton mSetting;
	private ImageButton mFlash;
	private ImageButton mHandsFree;
	private Chronometer mTimer;
//	private LinearLayout mOptLayout;

	private View mMainVideoView;
	private View mAudioView;
	private TextView mCallTipView;
	private TextView mWaitTipView; 
	
	private static int mCountBlankPacket;
	private boolean mbFlashOn = false;
	private KeyguardLock mKeyguardLock;
	private WakeLock mWakeLock;  
	 
	private int mMediaType;
	private int mCallType = Constant.CALL_TYPE_NORMAL;
	private boolean mbPrepareToCall;
	private boolean mbMakeCall;
	private boolean mbCallConnected; 	
	private boolean mbStartCall = false;
    private boolean mbWaitConnect = false; 
    private String mCallNumber;
	private int mCallId;
    private boolean mbMute = false;
    private Handler mHandler;
    private boolean mbAudioCall = false;

	//CallManageer
	private INetworkManager mNetworkManager;

	@Override
	protected void onNewIntent(Intent intent) {
		// TODO Auto-generated method stub
		super.onNewIntent(intent);
		setIntent(intent);
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_video_chat);		
		
		mHandler = new Handler();		
		getRemoteData();
		initConfig();
		initView(); 
		initViewByCallType();
		SipServiceCommand.getCallStatus(this, SipManager.getInstance().getAccount(), mCallId);

	}

	@Override
	protected void onResume() {
		Log.d(TAG,"onResume()");
		// TODO Auto-generated method stub
		if(!mbPrepareToCall || (mbStartCall && mbCallConnected)){
			showRemoteAndLocalView(true);
			loadRemoteVideo();
			delayLoadView();

			acquireWakeLock();
		}
		BroadcastEventReceiver.getBroadcastEventReceiver().registerEventObserverInner(this, this);

		super.onResume();
	}

	@Override
	protected void onPause() {
		Log.d(TAG,"onPause()");
		// TODO Auto-generated method stub
		if(!mbPrepareToCall || (mbStartCall && mbCallConnected)){
			showRemoteAndLocalView(false);

			releaseWakeLock();
//			getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		}
		super.onPause();
		BroadcastEventReceiver.getBroadcastEventReceiver().unRegisterEventObserverInner( this);

	}
	@Override
	protected void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
		Log.d(TAG,"onStart()");

	}

	@Override
	protected void onStop() {
		super.onStop();
		Log.d(TAG,"onStop()");

		if(mKeyguardLock != null){
			mKeyguardLock.reenableKeyguard();
		}
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		Log.d(TAG,"onDestroy()");
		showRemoteAndLocalView(false);

//	    mNetworkManager.unRegisterCallback(this);

		BroadcastEventReceiver.getBroadcastEventReceiver().unRegisterEventObserverInner(this);

		unRegisterCallback();

		super.onDestroy();
	}

	@Override
    public boolean onKeyDown(int keyCode, KeyEvent event)
    {
        if (keyCode == KeyEvent.KEYCODE_BACK )
        {
        	finish();
        	return true;
        }/*else  if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP){
        	return onVolumeChanged(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN);
        }*/
        return false;
    }

	private void getRemoteData(){
        Intent intent = getIntent();
        mCallType = intent.getIntExtra(Constant.ID_CALL_TYPE, Constant.CALL_TYPE_NORMAL);
        mbPrepareToCall = intent.getBooleanExtra(PREPARE_FOR_CALL_FLAG, false);
		mCallNumber = intent.getStringExtra(Constant.CALL_NUMBER);
		mCallId = intent.getIntExtra(Constant.SESSION_ID, -1);
		Log.d(TAG, "getRemoteData() mCallNumber:"+mCallNumber);
		if (SipManager.getInstance().isOutGoingVideo())
		{
			mMediaType = Constant.MEDIA_TYPE_VIDEO;//intent.getIntExtra(Constant.MEDIA_TYPE, Constant.MEDIA_TYPE_VIDEO);
		}else{
			mMediaType = Constant.MEDIA_TYPE_AUDIO;
		}
        mbMakeCall = intent.getBooleanExtra(Constant.IS_MAKE_CALL, false);
	}

	private void initView(){
		mViewRemoteVideoPreview 	= (FrameLayout) findViewById(R.id.previewSV);
		mViewLocalVideoPreview 		= (FrameLayout) findViewById(R.id.previewSV_local);
		mSvRemote = findViewById(R.id.surfaceIncomingVideo);
		mSvLocal = findViewById(R.id.surfacePreviewCapture);
		mViewLocalVideoPreviewInCall = (FrameLayout) findViewById(R.id.previewSV_local_incall);
		mSwitchCamera 				= (ImageButton) findViewById(R.id.switch_camera);
		mSetting						= (ImageButton) findViewById(R.id.setting);
		mFlash						= (ImageButton) findViewById(R.id.flash);
		mHandsFree					= (ImageButton) findViewById(R.id.hands_free);
		mSendVideo 					= (ImageButton) findViewById(R.id.send_video);
		mSwitchToAudio 					= (ImageButton) findViewById(R.id.switch_to_audio);
		mSwitchMute					= (ImageButton) findViewById(R.id.mute);
		mTimer 						= (Chronometer)this.findViewById(R.id.chronometer);
//		mOptLayout					= (LinearLayout) findViewById(R.id.opt_layout);
		mMainVideoView 				= findViewById(R.id.video_main_id);
		mAudioView 				= findViewById(R.id.video_2_voice_layout);
		TextView usernameView 				= (TextView)findViewById(R.id.user_name);
		if (mCallNumber != null){
			usernameView.setText(mCallNumber);
		}
		mCallTipView 	= (TextView)findViewById(R.id.send_video_tip);
		mWaitTipView = (TextView)findViewById(R.id.switch_to_audio_tip);
		
		mSwitchToAudio.setOnClickListener(this);
		mSendVideo.setOnClickListener(this);
		mSwitchCamera.setOnClickListener(this);
		mSetting.setOnClickListener(this);
		mSwitchMute.setOnClickListener(this);
		mFlash.setOnClickListener(this);
		mHandsFree.setOnClickListener(this);
		mTimer.setOnClickListener(this);
//		mViewLocalVideoPreviewInCall.setOnClickListener(this);

//		mOptLayout.setVisibility(View.VISIBLE);
		setSurfaceView();
	}

	private void setSurfaceView(){

		mSvRemote.getHolder().addCallback(new SurfaceHolder.Callback() {
			@Override
			public void surfaceCreated(SurfaceHolder surfaceHolder) {
				Logger.debug(TAG, "mSvRemote surfaceCreated " + mCallNumber);
			}

			@Override
			public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
				if (mCallNumber == null || mSvRemote.getVisibility() != View.VISIBLE){
					return;
				}
				mSvLocal.bringToFront();
				Logger.debug(TAG, "mSvRemote surfaceChanged " + mCallNumber);

				if (SipManager.getInstance().getCallStatus() != CALL_CONNECTED){
					return;
				}
				SipServiceCommand.setupIncomingVideoFeed(VideoChatActivity.this, SipManager.getInstance().getAccount(),
						mCallId, mSvRemote.getHolder().getSurface());
			}

			@Override
			public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
				if (mSvRemote.getVisibility() != View.VISIBLE){
					return;
				}
				Logger.debug(TAG, "mSvRemote surfaceDestroyed " + mCallNumber);
				SipServiceCommand.setupIncomingVideoFeed(VideoChatActivity.this, SipManager.getInstance().getAccount(), mCallId, null);
			}
		});
		mSvLocal.setVisibility(View.VISIBLE);
		mSvLocal.getHolder().addCallback(new SurfaceHolder.Callback() {
			@Override
			public void surfaceCreated(SurfaceHolder surfaceHolder) {
				Logger.debug(TAG, "mSvLocal surfaceCreated " + mCallNumber);
			}

			@Override
			public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
				Logger.debug(TAG, "mSvLocal startVideoPreview " + mCallNumber);
				if (mSvLocal.getVisibility() != View.VISIBLE){
					return;
				}

				mSvLocal.bringToFront();
				SipServiceCommand.startVideoPreview(VideoChatActivity.this, SipManager.getInstance().getAccount(), mCallId, mSvLocal.getHolder().getSurface());

				mSvLocal.postDelayed(new Runnable() {
					@Override
					public void run() {
						int camId = BACK_CAMERA_CAPTURE_DEVICE;
						//SipServiceCommand.switchVideoCaptureDevice(getContext(), mAccountID, mCallID, camId);
					}
				}, 500);
			}

			@Override
			public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
				//SipServiceCommand.stopVideoPreview(getContext(), mAccountID, mCallID);

				Logger.debug(TAG, "mSvLocal surfaceDestroyed " + mCallNumber);
			}
		});
	}

	private void initConfig(){
		mCountBlankPacket = 0;

//		setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
//		AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
//		am.setBluetoothScoOn(false);
//		am.setMode(AudioManager.MODE_IN_CALL);
	}

	private void initViewByCallType(){ 
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

		if (mbPrepareToCall){
			ready4MakeCall();
		}else{
			ready4Call();				
		} 
	}
 	
	private void ready4Call(){
		mTimer.setBase(SystemClock.elapsedRealtime());
		mTimer.start();

		showRemoteAndLocalView(true);
//		mSendVideo.setBackgroundResource(R.drawable.icon_stop_rec_press);
	}

	private void ready4MakeCall(){
		showRemoteAndLocalView(false);
		mSendVideo.setBackgroundResource(R.drawable.call_stop_n); 

		if(TextUtils.isEmpty(mCallNumber)){
			finish(); 
		}  
		startSendVideoEx();
	}

	private void acquireWakeLock(){
		PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
		mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
				| PowerManager.ON_AFTER_RELEASE, this.getClass().getCanonicalName());
		mWakeLock.acquire();
	}

	private void releaseWakeLock() {
		if (mWakeLock !=null&& mWakeLock.isHeld()) {
			mWakeLock.release();
			mWakeLock =null;
		}
	}

//	public boolean onVolumeChanged(boolean bDown){
//		if(mAVSession != null){
//			return mAVSession.onVolumeChanged(bDown);
//		}
//		return false;
//	}


	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		int vid = v.getId();
		switch(vid){
		case R.id.switch_to_audio:
			//switch video to audio
			if (mAudioView.getVisibility() == View.GONE){
				updateToAudioView();
			}
			break;
		case R.id.previewSV_local_incall:
			{
				switchLocalAndRemoteView();
			}
			break;
		case R.id.send_video:
			Log.d(TAG, "onclick mbStartCall:"+mbStartCall+", mbCallConnected:" + mbCallConnected+", mbPrepareToCall:"+mbPrepareToCall); 
			if(mbPrepareToCall){ 
				if (mbStartCall){ 
					stopSession(); 
				}else{
					startSession();
				}
			} else{
				stopSession();
			} 
			break;
		case R.id.switch_camera:
			if (mAudioView.getVisibility() == View.GONE){
			}
			break;
		case R.id.setting:
			break;
		case R.id.mute:
			mbMute = !mbMute;
			break;
		case R.id.flash:
			flashSwitch(!mbFlashOn);
			break;
		case R.id.hands_free:
			break;
		}
	}
 
	private void stopSession(){ 
		Log.d(TAG, "stopSession hangup:"+mCallNumber);
		mbStartCall = false;
		SipServiceCommand.hangUpCall(VideoChatActivity.this, SipManager.getInstance().getAccount(), mCallId);
		hideAudioView();
	}
	
	private void startSession(){ 
		startSendVideoEx(); 
	}
	
	private void flashSwitch(boolean isStart){
		mbFlashOn = !mbFlashOn;
		if(mbFlashOn){
			mFlash.setBackgroundResource(R.drawable.icon_flashoff);
		}else{
			mFlash.setBackgroundResource(R.drawable.icon_flash);
		}
	}

	private void startSendVideoEx(){
	}

	private void initAVSession( ){
	     mHandsFree.setBackgroundResource(R.drawable.icon_speaker_on);
	}
	
	private void changeButtonStatus(final boolean startCall) {
		// TODO Auto-generated method stub
		mWaitTipView.setText(getString(R.string.video_2_audio_call));
	}

	private void showRemoteAndLocalView(boolean show){ 
		if (show){
			mViewLocalVideoPreview.setVisibility(View.GONE);
			//mViewLocalVideoPreview.removeAllViews();

			mViewRemoteVideoPreview.setVisibility(View.VISIBLE); 
			mViewLocalVideoPreviewInCall.setVisibility(View.VISIBLE);
		}else{
			mViewRemoteVideoPreview.setVisibility(View.GONE);
			//mViewRemoteVideoPreview.removeAllViews();
			mViewLocalVideoPreviewInCall.setVisibility(View.GONE);
			//mViewLocalVideoPreviewInCall.removeAllViews();
			//mViewLocalVideoPreview.removeAllViews();
			mViewLocalVideoPreview.setVisibility(View.VISIBLE);  
		}
	}
	
	private void switchLocalAndRemoteView(){
		showRemoteAndLocalView(false);

	}
	
	//加载用于显示远程视频流的view
	private void loadRemoteVideo(){
	}
	
	//加载用于显示本地视频流的view,并开始向远端发送视频流
	private void startStopLocalVideo(final boolean bStart) {
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
			}
		});
	}

	private final TimerTask mTimerTaskBlankPacket = new TimerTask() {
		@Override
		public void run() {
			Log.d(TAG,
					"Resending Blank Packet "
							+ String.valueOf(mCountBlankPacket));
			if (mCountBlankPacket < 3) {
				mCountBlankPacket++;
			} else {
				cancel();
				mCountBlankPacket = 0;
			}
		}
	};

	private void cancelBlankPacket() {
	}
	
	private void startCall(){
		Log.d(TAG, "startCall");
		initAVSession();
		showRemoteAndLocalView(true);
		startStopLocalVideo(true);
		loadRemoteVideo();
		changeButtonStatus(true); 
	}
	
	private void endCall(){
		Log.d(TAG, "endCall");
//		if(mCallType == CallManager.CALL_TYPE_NORMAL){
			unRegisterCallback();
			finish();
//		}else{
//			stopProgressDialog();
//			
//			mCallTipView.setText(getString(R.string.call));
//			
//			startStopLocalVideo(false);
//			showRemoteAndLocalView(false);
//			addLocalView();
//			changeButtonStatus(false);
//			mTimer.setBase(SystemClock.elapsedRealtime());
//			mTimer.stop();
//			mbFlashOn = false;
//			mbCallConnected = false;
//			mCallManager.flashSwitch(mCallNumber, false);
//			mFlash.setBackgroundResource(R.drawable.icon_flash); 
//			//reset codec, lyz@xdja.com add.
////			SipStack.setCodecs_2(NgnConfigurationEntry.DEFAULT_MEDIA_CODECS);
//		}
			
		mTimer.stop();

	}

	@Override
	public void notifyRegState(String account, int code, String reason, long expiration) {

		Log.i(TAG, "notifyRegState, callStateCode:"+reason);
	}

	@Override
	public void notifyIncomingCall(String accountID, int callID, String displayName, String remoteUri, boolean isVideo) {

	}

	@Override
	public void notifyCallState(String accountID, int callID, int callStateCode, int callStatusCode, long connectTimestamp) {

		Log.i(TAG, "notifyCallState, callStateCode:"+callStateCode);
		if (pjsip_inv_state.PJSIP_INV_STATE_CALLING==callStateCode) {
		} else if (pjsip_inv_state.PJSIP_INV_STATE_INCOMING==callStateCode) {
		} else if (pjsip_inv_state.PJSIP_INV_STATE_EARLY==callStateCode) {
			//响铃
		} else if (pjsip_inv_state.PJSIP_INV_STATE_CONNECTING==callStateCode) {
			//连接中
		} else if (pjsip_inv_state.PJSIP_INV_STATE_CONFIRMED==callStateCode) {
			//连接成功
			SipManager.getInstance().setCallStatus(CALL_CONNECTED);

		} else if (pjsip_inv_state.PJSIP_INV_STATE_DISCONNECTED==callStateCode) {
			SipManager.getInstance().setCallStatus(CALL_DISCONNECTED);
			if (VideoChatActivity.this.isFinishing()){
				return;
			}
			finish();
		} else if (pjsip_inv_state.PJSIP_INV_STATE_NULL==callStateCode) {
			//未知错误

		}
	}

	@Override
	public void notifyCallMediaState(String accountID, int callID, MediaState stateType, boolean stateValue) {

	}

	@Override
	public void notifyChangeNetwork() {

	}


	private void delayLoadView(){
		startStopLocalVideo(true);
	}
	
	private void unRegisterCallback(){
	}

	private void goToRegisterHome(){ 
		Intent home = new Intent(this, LoginActivity.class);
		home.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);    
		startActivity(home);	 
	}
	
	//Video switch to audio.
	private void hideAudioView(){
		mAudioView.setVisibility(View.GONE);		
	}
	
	private void updateToAudioView(){ 
		mbAudioCall = true;
		
		Toast.makeText(VideoChatActivity.this, getString(R.string.call_video_switch_2_audio), 3000).show();

		mSwitchCamera.setVisibility(View.GONE);
		
		mViewLocalVideoPreview.setVisibility(View.GONE);
		mViewRemoteVideoPreview.setVisibility(View.GONE);
		mViewLocalVideoPreviewInCall.setVisibility(View.GONE);
		
		mMainVideoView.setBackgroundResource(R.drawable.bg_set);
		mAudioView.setVisibility(View.VISIBLE);
		
//		mSwitchToAudio.setImageResource(resId);
	}


	private void startProgressDialog(int strId){ 
		showError(getString(strId));
	}  
	      
	private void stopProgressDialog(){   
		try{
			hideLoading();
		}catch(Exception ex){
			Log.d(TAG, "ex:"+ex.getMessage());
		}
	}    

	@Override
	public void onTrimMemory(int level){
		Log.i(TAG, "onTrimMemory, level:"+level);
		switch(level){
			case TRIM_MEMORY_UI_HIDDEN:
			{
				
			}
			break;
		}
		super.onTrimMemory(level);
	}
	
	@Override
	public void onLowMemory(){
		Log.d(TAG, "onLowMemory"); 
		//...
		
		super.onLowMemory();
	}

}
